import { IWorld } from '../common/world.interface';
import { BorderRendererComponent } from '../components/border-renderer.component';
import { ColliderComponent } from '../components/collider.component';
import { LocationComponent } from '../components/location.component';
import { Entity } from '../entities/entity';
import { DEF_STROKE_STYLE } from './render.system';
import { System } from './system';

export class CollionDebugSystem extends System {
  #entities = new Map<Entity, Entity[]>();

  constructor(
    private readonly entitiesToRender: Entity[] = [],
    private readonly strokeStyle = DEF_STROKE_STYLE
  ) {
    super();
  }

  onStart(world: IWorld): void {
    for (const entity of this.entitiesToRender) {
      this.#entities.set(entity, []);
    }
  }

  onUpdate(world: IWorld, dt: number) {
    const missingEntities: Entity[] = [];

    for (const [entity, newEntities] of this.#entities) {
      const entityLocationComponent = world.findComponentByEntity(entity, LocationComponent);
      const entityColliderComponent = world.findComponentByEntity(entity, ColliderComponent);

      if (!entityLocationComponent || !entityColliderComponent) {
        missingEntities.push(entity);
        continue;
      }

      for (const newEntity of newEntities) {
        world.removeEntity(newEntity);
      }

      newEntities.splice(0, newEntities.length);

      for (const config of entityColliderComponent.configs) {
        const newEntity = new Entity('Collision Render Entity');
        const newLocationComponent = new LocationComponent(
          entityLocationComponent.location.add(config.relativeLocation)
        );
        const newBorderRendererComponent = new BorderRendererComponent(config.dimension, this.strokeStyle);
        world.addEntity(newEntity);
        world.attachComponentToEntity(LocationComponent, newLocationComponent, newEntity);
        world.attachComponentToEntity(BorderRendererComponent, newBorderRendererComponent, newEntity);
        newEntities.push(newEntity);
      }
    }

    for (const entity of missingEntities) {
      this.#entities.delete(entity);
    }
  }

  onFinish() {
    this.#entities.clear();
  }
}
